/*
 * Conditions Of Use
 *
 * This software was developed by employees of the National Institute of
 * Standards and Technology (NIST), an agency of the Federal Government.
 * Pursuant to title 15 Untied States Code Section 105, works of NIST
 * employees are not subject to copyright protection in the United States
 * and are considered to be in the public domain.  As a result, a formal
 * license is not needed to use the software.
 *
 * This software is provided by NIST as a service and is expressly
 * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
 * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
 * AND DATA ACCURACY.  NIST does not warrant or make any representations
 * regarding the use of the software or the results thereof, including but
 * not limited to the correctness, accuracy, reliability or usefulness of
 * the software.
 *
 * Permission to use this software is contingent upon your acceptance
 * of the terms of this agreement
 *
 * .
 *
 */
/*
 * Bug reports contributed by Joao Paulo, Stephen Jones,
 * John Zeng and Alstair Cole.
 *
 */
/*******************************************************************************
 * Product of NIST/ITL Advanced Networking Technologies Division (ANTD).        *
 *******************************************************************************/
package com.jswitch.sip.header;


import com.jswitch.common.exception.InvalidArgumentException;
import com.jswitch.sip.*;
import com.jswitch.sip.adress.Address;
import com.jswitch.sip.adress.AddressImpl;

import java.text.ParseException;

import static com.jswitch.common.constant.Separators.SEMICOLON;

public final class Contact extends AddressParametersHeader implements ContactHeader {

    private static final long serialVersionUID = 1677294871695706288L;
    public static final String ACTION = ParameterNames.ACTION;
    public static final String PROXY = ParameterNames.PROXY;
    public static final String REDIRECT = ParameterNames.REDIRECT;
    public static final String EXPIRES = ParameterNames.EXPIRES;
    public static final String Q = ParameterNames.Q;

    private ContactList contactList;

    protected boolean wildCardFlag;

    public Contact() {
        super(NAME);
    }

    public void setParameter(String name, String value) throws ParseException {
        NameValue nv = parameters.getNameValue(name);
        if (nv != null) {
            nv.setValueAsObject(value);
        } else {
            nv = new NameValue(name, value);
            if (name.equalsIgnoreCase("methods"))
                nv.setQuotedValue();
            this.parameters.set(nv);
        }
    }


    protected String encodeBody() {
        return encodeBody(new StringBuilder()).toString();
    }

    public StringBuilder encodeBody(StringBuilder buffer) {
        if (wildCardFlag) {
            buffer.append('*');
        } else {
            if (address.getAddressType() == AddressImpl.NAME_ADDR) {
                address.encode(buffer);
            } else {
                buffer.append('<');
                address.encode(buffer);
                buffer.append('>');
            }
            if (!parameters.isEmpty()) {
                buffer.append(SEMICOLON);
                parameters.encode(buffer);
            }
        }

        return buffer;
    }


    public ContactList getContactList() {
        return contactList;
    }


    public boolean getWildCardFlag() {
        return wildCardFlag;
    }


    public Address getAddress() {
        return address;
    }

    public NameValueList getContactParms() {
        return parameters;
    }

    public int getExpires() {
        return getParameterAsInt(EXPIRES);
    }


    public void setExpires(int expiryDeltaSeconds) {
        Integer deltaSeconds = Integer.valueOf(expiryDeltaSeconds);
        this.parameters.set(EXPIRES, deltaSeconds);
    }

    public float getQValue() {
        return getParameterAsFloat(Q);
    }

    public void setContactList(ContactList cl) {
        contactList = cl;
    }

    public void setWildCardFlag(boolean w) {
        this.wildCardFlag = true;
        this.address = new AddressImpl();
        this.address.setWildCardFlag();
    }

    public void setAddress(Address address) {
        if (address == null)
            throw new NullPointerException("null address");
        this.address = (AddressImpl) address;
        this.wildCardFlag = false;
    }

    public void setQValue(float qValue) throws InvalidArgumentException {
        if (qValue != -1 && (qValue < 0 || qValue > 1))
            throw new InvalidArgumentException("SIP Exception, Contact, setQValue(), the qValue is not between 0 and 1");
        this.parameters.set(Q, qValue);
    }

    public Object clone() {
        Contact retval = (Contact) super.clone();
        if (this.contactList != null)
            retval.contactList = (ContactList) this.contactList.clone();
        return retval;
    }


    public void setWildCard() {
        this.setWildCardFlag(true);

    }


    public boolean isWildCard() {

        return this.address.isWildcard();
    }

    public boolean equals(Object other) {
        return (other instanceof ContactHeader) && super.equals(other);
    }

    public void removeSipInstanceParam() {
        if (parameters != null)
            parameters.delete(ParameterNames.SIP_INSTANCE);
    }

    public String getSipInstanceParam() {
        return (String) parameters.getValue(ParameterNames.SIP_INSTANCE);
    }

    public void setSipInstanceParam(String value) {
        this.parameters.set(ParameterNames.SIP_INSTANCE, value);
    }


    public void removePubGruuParam() {
        if (parameters != null)
            parameters.delete(ParameterNames.PUB_GRUU);
    }

    public String getPubGruuParam() {
        return (String) parameters.getValue(ParameterNames.PUB_GRUU);
    }

    public void setPubGruuParam(String value) {
        this.parameters.set(ParameterNames.PUB_GRUU, value);
    }

    public void removeTempGruuParam() {
        if (parameters != null)
            parameters.delete(ParameterNames.TEMP_GRUU);
    }

    public String getTempGruuParam() {
        return (String) parameters.getValue(ParameterNames.TEMP_GRUU);
    }

    public void setTempGruuParam(String value) {
        this.parameters.set(ParameterNames.TEMP_GRUU, value);
    }
}
